﻿using Core.DataAccess.Model.Project.Comment;
using Core.Framework.EntityExtend;
using Core.Framework.Model.Common;
using Core.Framework.Redis;
using Core.IBusiness.IComment;
using Core.IBusiness.IComment.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using Core.Framework.Util.Common;
using System.Linq.Expressions;
using Core.IBusiness.ISocketModule;
using Core.Framework.Model.WebSockets;
using Core.Framework.Util;
using Core.DataAccess.Model.Project.Information;
using Core.IBusiness.IPushModule;
using Microsoft.AspNetCore.Http;

namespace Core.Business.CommentModule
{
    public class Comment: BaseHttpPipelineInfo, ICommentModule
    {
        //private IQueue iQueue { get; set; }
        private IArticlePush iArticlePush { get; set; }

        public Comment( IArticlePush iArticlePush, IHttpContextAccessor iHttp) : base(iHttp)
        {
            this.iArticlePush = iArticlePush;
        }



        public MethodResult<int> CommentAttributeExec(CommentAttribute model, SqlExecType sqlExecType)
        {
            return Utils.SqlExecType<ProjectCommentContext, CommentAttribute>(model,
                        sqlExecType,
                        a => a.Id == model.Id);
        }

        public MethodResult<int> CommentExec(CommentList model, SqlExecType sqlExecType, ApiClientInfo clientInfo)
        {

            var result = Utils.SqlExecType<ProjectCommentContext,CommentList>(model,
                        sqlExecType,
                        a => a.Id == model.Id & a.ProjectToken == model.ProjectToken,
                        afterAction:(context) => {

                            if (sqlExecType == SqlExecType.insert)
                            {

                                #region 评论默认属性处理
                                List<CommentAttribute> attrs = new List<CommentAttribute>();

                                attrs.Add(new CommentAttribute
                                {
                                    CommentKey = model.Id,
                                    UserKey = model.UserKey,
                                    RegTime = DateTime.Now,
                                    Type = (int)CommentAttributeEnum.Fabulous
                                });

                                context
                                    .CommentAttribute
                                    .BulkInsert(attrs);
                                #endregion

                                #region 推送模块
                                using (var infocontext = new ProjectInformationContext())
                                {
                                    var articleModel = infocontext
                                                    .InformationList
                                                    .Where(a => a.Id == model.InformationKey).Select(a => new {
                                                        id = a.Id,
                                                        title = a.Title,
                                                        Content = a.Content,
                                                        useKey = a.UserKey
                                                    }).FirstOrDefault();

                                    if (articleModel?.id > 0)
                                    {

                                        #region Use iArticlePush Module

                                        // Start 构造Content数据模型
                                        var article = articleModel.Content.TryToEntity<ContentAndImages>(out string error)
                                                 ?? new ContentAndImages();

                                        if (!string.IsNullOrWhiteSpace(error))
                                            // 序列化失败的话，则直接使用content的数据
                                            article.Content = articleModel.Content;

                                        var articleContent = new { content = article.GetContentSubStringByLength(), images = article.Images };
                                        
                                        // ------------------------------------------------------------------
                                        var comment = model.Content.TryToEntity<ContentAndImages>(out string errorByComment)
                                                 ?? new ContentAndImages();

                                        if (!string.IsNullOrWhiteSpace(errorByComment))
                                            // 序列化失败的话，则直接使用content的数据
                                            comment.Content = model.Content;

                                        var commentContent = new { content = comment.GetContentSubStringByLength(), images = comment.Images };
                                        // End

                                        this.iArticlePush.InfoComment(new IBusiness.IPushModule.Model.InfoCommentModel {
                                            Title = $"{clientInfo.UserName}给你评论:{commentContent.content}",
                                            ClientToken = clientInfo.Token,
                                            MessageKey = articleModel.useKey.ToString(),
                                            MessageContent = new IBusiness.IPushModule.Model.InfoCommentContent
                                            {
                                                Info = new IBusiness.IPushModule.Model.InfoCommentInfoModel {
                                                    Id = articleModel.id,
                                                    Title = articleModel.title,
                                                    Content = articleContent.TryToJson()
                                                },
                                                Comment = new IBusiness.IPushModule.Model.CommentModel {
                                                    Id = model.Id,
                                                    Content = commentContent.TryToJson()
                                                }
                                            }
                                        });

                                        #endregion

                                        #region iQueue 推送已过期
                                        //iQueue.Publish(new QueryMessage
                                        //{
                                        //    MessageKey = modelinfo.useKey.ToString(),
                                        //    Content = new
                                        //    {
                                        //        infoKey = modelinfo.id,
                                        //        title = modelinfo.title,
                                        //        content = modelinfo.Content,
                                        //        commentContent = model.Content
                                        //    }.TryToJson(),
                                        //    Parameter = new { type = "infocomment" }.TryToJson(),
                                        //    ClientToken = clientToken,
                                        //    MessageType = MessageTypeEnum.Single,
                                        //    Template = "websocket"
                                        //});
                                        #endregion
                                    }

                                }
                                #endregion

                            }

                        });

            return result;

        }

        public MethodResult<int> CommentReplyExec(CommentReply model, SqlExecType sqlExecType, string clientToken)
        {
            return Utils.SqlExecType<ProjectCommentContext, CommentReply>(model,
                        sqlExecType,
                        a => a.Id == model.Id,
                        afterAction: (context) => {

                            if (sqlExecType == SqlExecType.insert)
                            {
                                #region Default Attrs
                                List<CommentAttribute> attrs = new List<CommentAttribute>();

                                attrs.Add(new CommentAttribute
                                {
                                    ReplyKey = model.Id,
                                    UserKey = 0,
                                    RegTime = DateTime.Now,
                                    Type = (int)CommentAttributeEnum.Fabulous
                                });

                                context
                                    .CommentAttribute
                                    .BulkInsert(attrs);
                                #endregion

                                #region Push Module
                                using (var contextinfo = new ProjectCommentContext())
                                {
                                    var commmm = contextinfo.CommentList.Where(a => a.Id == model.CommentKey).FirstOrDefault();

                                    if (commmm?.Id > 0)
                                    {

                                        // Start 构造Content数据模型
                                        var reply = model.Content.TryToEntity<ContentAndImages>(out string error)
                                                 ?? new ContentAndImages();

                                        if (!string.IsNullOrWhiteSpace(error))
                                            // 序列化失败的话，则直接使用content的数据
                                            reply.Content = reply.Content;

                                        var replyContent = new { content = reply.GetContentSubStringByLength(), images = reply.Images };

                                        // ------------------------------------------------------------------
                                        var comment = commmm.Content.TryToEntity<ContentAndImages>(out string errorByComment)
                                                 ?? new ContentAndImages();

                                        if (!string.IsNullOrWhiteSpace(errorByComment))
                                            // 序列化失败的话，则直接使用content的数据
                                            comment.Content = model.Content;

                                        var commentContent = new { content = comment.GetContentSubStringByLength(), images = comment.Images };
                                        // End

                                        iArticlePush.InfoReplyComment(new IBusiness.IPushModule.Model.InfoReplyCommentModel {
                                            Title = $"{iClientInfo.UserName}给你回复:{replyContent.content}",
                                            ClientToken = iClientInfo.Token,
                                            MessageKey = model.CommentUserKey.ToString(),
                                            MessageContent = new IBusiness.IPushModule.Model.InfoReplyCommentContent {
                                                Info = new IBusiness.IPushModule.Model.InfoModel {
                                                    Id = commmm.InformationKey
                                                },
                                                Comment = new IBusiness.IPushModule.Model.CommentModel {
                                                    Id = commmm.Id,
                                                    Content = commentContent.TryToJson()
                                                },
                                                Reply = new IBusiness.IPushModule.Model.ReplyModel {
                                                    Id = model.Id,
                                                    Content = replyContent.TryToJson()
                                                }
                                            }
                                        });

                                        #region iQueue 已过期
                                        //iQueue.Publish(new QueryMessage
                                        //{
                                        //    MessageKey = model.CommentUserKey.ToString(),
                                        //    Content = new
                                        //    {
                                        //        infoKey = commmm.InformationKey,
                                        //        commentKey = commmm.Id,
                                        //        commentContent = commmm.Content,
                                        //        replyKey = model.Id,
                                        //        replyContent = model.Content
                                        //    }.TryToJson(),
                                        //    Parameter = new { type = "inforeplycomment" }.TryToJson(),
                                        //    ClientToken = clientToken,
                                        //    MessageType = MessageTypeEnum.Single,
                                        //    Template = "websocket"
                                        //});
                                        #endregion
                                    }
                                }
                                #endregion

                            }

                        });
        }


        public MethodResult<int> CommentReplyStar(int replyKey, int userKey, string clientToken)
        {
            var redis = new CommentRedisCache(replyKey);
            redis.CommentReplyStar(userKey);


            using (var context = new ProjectCommentContext())
            {
                var model = context.CommentReply.Where(a => a.Id == replyKey).Select(a => new {
                    a.Id,
                    a.CommentKey,
                    a.Content,
                    a.ReplyUserKey
                }).FirstOrDefault();

                if (model?.Id > 0)
                {

                    var commmm = context.CommentList.Where(a => a.Id == model.CommentKey).FirstOrDefault();

                    #region iQueue 已过期
                    //iQueue.Publish(new QueryMessage
                    //{
                    //    MessageKey = model.ReplyUserKey.ToString(),
                    //    Content = new
                    //    {
                    //        infoKey = commmm.InformationKey,
                    //        commentKey = commmm.Id,
                    //        commentContent = commmm.Content,
                    //        replyKey = model.Id,
                    //        replyContent = model.Content
                    //    }.TryToJson(),
                    //    Parameter = new { type = "commentreplystar" }.TryToJson(),
                    //    ClientToken = clientToken,
                    //    MessageType = MessageTypeEnum.Single,
                    //    Template = "websocket"
                    //});
                    #endregion

                    #region Push Module 

                    // Start 构造Content数据模型
                    var reply = model.Content.TryToEntity<ContentAndImages>(out string error)
                             ?? new ContentAndImages();

                    if (!string.IsNullOrWhiteSpace(error))
                        // 序列化失败的话，则直接使用content的数据
                        reply.Content = reply.Content;

                    var replyContent = new { content = reply.GetContentSubStringByLength(), images = reply.Images };

                    this.iArticlePush.CommentReplyStar(new IBusiness.IPushModule.Model.CommentReplyStarModel {
                        Title = $"{iClientInfo.UserName}赞了你的回复:{replyContent.content}",
                        ClientToken = iClientInfo.Token,
                        MessageKey = model.ReplyUserKey.ToString(),
                        MessageContent = new IBusiness.IPushModule.Model.CommentReplyStarContent {
                            Info = new IBusiness.IPushModule.Model.InfoModel {
                                Id = commmm.InformationKey
                            },
                            Reply = new IBusiness.IPushModule.Model.ReplyModel {
                                Id = model.Id,
                                Content = replyContent.TryToJson()
                            },
                            Comment = new IBusiness.IPushModule.Model.CommentModel
                            {
                                Id = commmm.Id
                            }
                        }
                    });

                    #endregion

                }
                else
                {
                    return new MethodResult<int> { IsFinished = false, Discription = "信息不存在" };
                }

            }

            return new MethodResult<int> { IsFinished = true, Date = 1 };
        }

        public MethodResult<int> CommentStar(int infoKey, int userKey, string clientToken)
        {
            var redis = new CommentRedisCache(infoKey);
            redis.CommentStar(userKey);


            using (var context = new ProjectCommentContext())
            {
                var model = context.CommentList.Where(a => a.Id == infoKey).Select(a => new {
                    a.Id,
                    a.Content,
                    a.InformationKey,
                    a.UserKey
                }).FirstOrDefault();

                if (model?.Id > 0)
                {
                    #region Push Module

                    var comment = model.Content.TryToEntity<ContentAndImages>(out string error)
                                                 ?? new ContentAndImages();

                    if (!string.IsNullOrWhiteSpace(error))
                        // 序列化失败的话，则直接使用content的数据
                        comment.Content = model.Content;

                    var commentContent = new { content = comment.GetContentSubStringByLength(), images = comment.Images };

                    this.iArticlePush.CommentStar(new IBusiness.IPushModule.Model.CommentStarModel {
                        Title = $"{iClientInfo.UserName}赞了你的评论:{commentContent.content}",
                        ClientToken = iClientInfo.Token,
                        MessageKey = model.UserKey.ToString(),
                        MessageContent = new IBusiness.IPushModule.Model.CommentStarContent {
                            Info = new IBusiness.IPushModule.Model.InfoModel {
                                Id = model.InformationKey
                            },
                            Comment = new IBusiness.IPushModule.Model.CommentModel {
                                Id = model.Id,
                                Content = commentContent.TryToJson()
                            }
                        }
                    });
                    #endregion

                    #region iQueue 已过期
                    //iQueue.Publish(new QueryMessage
                    //{
                    //    MessageKey = model.UserKey.ToString(),
                    //    Content = new
                    //    {
                    //        infoKey = model.InformationKey,
                    //        commentKey = model.Id,
                    //        title = model.Content
                    //    }.TryToJson(),
                    //    Parameter = new { type = "commentstar" }.TryToJson(),
                    //    ClientToken = clientToken,
                    //    MessageType = MessageTypeEnum.Single,
                    //    Template = "websocket"
                    //});
                    #endregion
                }
                else
                {
                    return new MethodResult<int> { IsFinished = false, Discription = "信息不存在" };
                }

            }


            return new MethodResult<int> { IsFinished = true, Date = 1 };
        }

        public MethodResult<int> CommentUnReplyStar(int replyKey, int userKey, string projectToken)
        {
            var redis = new CommentRedisCache(replyKey);
            redis.CommentReplyUnStar(userKey);
            return new MethodResult<int> { IsFinished = true, Date = 1 };
        }

        public MethodResult<int> CommentUnStar(int infoKey, int userKey, string projectToken)
        {
            var redis = new CommentRedisCache(infoKey);
            redis.CommentUnStar(userKey);
            return new MethodResult<int> { IsFinished = true, Date = 1 };
        }



        public MethodResult<List<CommentReply>> GetCommentReply(int commentKey, Pagination pagination, List<CommentAttributeEnum> attributeEnums = null)
        {

            try
            {

                var redis = new CommentRedisCache(commentKey);

                using (var context = new ProjectCommentContext())
                {
                    // 查询出回复的相关信息
                    var query = context
                        .CommentReply
                        .Where(a => a.CommentKey == commentKey)
                        .Pagination(pagination);


                    if (query?.Count > 0)
                    {
                        // 是否查询属性
                        if (attributeEnums?.Count > 0)
                        {
                            // 一次性查出所有内容的属性
                            var attributes =
                                    context
                                        .CommentAttribute
                                        .Where(a =>
                                                    query.Select(b => b.Id).Contains((int)a.ReplyKey)
                                                    && attributeEnums.Select(b => (int)b).Contains(a.Type))
                                        .ToList();


                            foreach (var item in query)
                            {
                                // 按照内容分组归类属性
                                item.CommentAttributes = attributes.Where(a => a.ReplyKey == item.Id).ToList();

                                // 获取redis的点赞信息
                                var stars = redis.GetCommentReplyStar();

                                // 获取点在信息
                                var fabulous = item.CommentAttributes
                                    .Where(a => a.Type == (int)CommentAttributeEnum.Fabulous & a.ReplyKey == item.Id)
                                    .FirstOrDefault();

                                // 数据库无点赞信息
                                if (string.IsNullOrWhiteSpace(fabulous?.Extend))
                                {
                                    // redis是否存在点在信息
                                    if (stars?.Count > 0)
                                    {
                                        fabulous.Extend = string.Join(',', stars.Select(a => a.Key));
                                    }
                                }
                                else
                                {
                                    if (stars?.Count > 0)
                                    {
                                        // 数据库数据格式化
                                        var list = fabulous.Extend.TrimEnd(',').TrimStart(',').Split(',').ToList();

                                        // 处理redis获取到的数据
                                        var redisStars = stars.Select(a => a.Key).ToList();

                                        // 合并结果集并去重
                                        fabulous.Extend = string.Join(',', list.Union(redisStars));
                                    }
                                    else
                                    {
                                        fabulous.Extend = fabulous.Extend.TrimEnd(',').TrimStart(',');
                                    }
                                }

                            }
                        }
                    }

                    return new MethodResult<List<CommentReply>> { IsFinished = true, Date = query };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<List<CommentReply>> { IsFinished = false, Discription = e.Message };
            }

        }

        public MethodResult<List<CommentList>> GetComments(int infoKey, bool isGetReply, Pagination pagination, List<CommentAttributeEnum> attributeEnums = null, string type = null)
        {
            try
            {

                using (var context = new ProjectCommentContext())
                {

                    Expression<Func<CommentList, bool>> wherecc = a => a.InformationKey == infoKey;

                    if (!string.IsNullOrWhiteSpace(type))
                    {
                        wherecc = wherecc.And(a => a.Type == type);
                    }

                    // 查询出回复的相关信息
                    var query = context
                        .CommentList
                        .Where(wherecc)
                        .Pagination(pagination);


                    if (query?.Count > 0)
                    {

                        List<CommentReply> replys = new List<CommentReply>();
                        Pagination replysPagination = new Pagination { page = 1, rows = 900 };

                        // 是否查询属性
                        if (attributeEnums?.Count > 0)
                        {

                            Expression<Func<CommentAttribute, bool>> where = a =>
                                                    attributeEnums.Select(b => (int)b).Contains(a.Type) && query.Select(b => b.Id).Contains(a.CommentKey);

                            // 是否查询回复内容
                            if (isGetReply)
                            {
                                
                                List<long> infoKeys = query.Select(b => (long)b.Id).ToList<long>();

                                replys = context
                                            .CommentReply
                                            .Where(a => infoKeys.Contains(a.CommentKey))
                                            .Pagination(replysPagination);

                                where = where.Or(a =>
                                            (
                                                attributeEnums.Select(b => (int)b).Contains(a.Type)
                                                && replys.Select(b => b.Id).Contains((int)a.ReplyKey)
                                            )
                                           );
                            }


                            // 一次性查出所有内容的属性
                            var _attributes =
                                    context
                                        .CommentAttribute
                                        .Where(where);


                            var attributes = _attributes.ToList();





                            foreach (var item in query)
                            {



                                {
                                    var redis = new CommentRedisCache(item.Id);

                                    // 按照内容分组归类属性
                                    item.CommentAttributes = attributes.Where(a => a.CommentKey == item.Id).ToList();

                                    // 获取redis的点赞信息
                                    var stars = redis.GetCommentStar();

                                    // 获取点在信息
                                    var fabulous = item.CommentAttributes
                                        .Where(a => a.Type == (int)CommentAttributeEnum.Fabulous & a.CommentKey == item.Id)
                                        .FirstOrDefault();

                                    // 数据库无点赞信息
                                    if (string.IsNullOrWhiteSpace(fabulous?.Extend))
                                    {
                                        // redis是否存在点在信息
                                        if (stars?.Count > 0)
                                        {
                                            fabulous.Extend = string.Join(',', stars.Select(a => a.Key));
                                        }
                                    }
                                    else
                                    {
                                        if (stars?.Count > 0)
                                        {
                                            // 数据库数据格式化
                                            var list = fabulous.Extend.TrimEnd(',').TrimStart(',').Split(',').ToList();

                                            // 处理redis获取到的数据
                                            var redisStars = stars.Select(a => a.Key).ToList();

                                            // 合并结果集并去重
                                            fabulous.Extend = string.Join(',', list.Union(redisStars));
                                        }
                                        else
                                        {
                                            fabulous.Extend = fabulous.Extend.TrimEnd(',').TrimStart(',');
                                        }
                                    }
                                }

                                // 构造回复相关信息
                                if (isGetReply)
                                {
                                    item.Reply = new Reply();

                                    item.Reply.Pagination = replysPagination;

                                    item.Reply.Date = replys.Where(a => a.CommentKey == item.Id).ToList();

                                    if (item.Reply.Date.Count > 0)
                                    {
                                        foreach (var itemReply in item.Reply.Date)
                                        {
                                            itemReply.CommentAttributes = attributes.Where(a => a.ReplyKey == itemReply.Id).ToList();

                                            var redis = new CommentRedisCache(itemReply.Id);

                                            // 获取redis的回复点赞信息
                                            var starsReply = redis.GetCommentReplyStar();

                                            // 获取点在信息
                                            var fabulousReply = itemReply.CommentAttributes
                                                .Where(a => a.Type == (int)CommentAttributeEnum.Fabulous & a.ReplyKey == item.Id)
                                                .FirstOrDefault() ?? new CommentAttribute();

                                            // 数据库无点赞信息
                                            if (string.IsNullOrWhiteSpace(fabulousReply?.Extend))
                                            {
                                                // redis是否存在点在信息
                                                if (starsReply?.Count > 0)
                                                {
                                                    fabulousReply.Extend = string.Join(',', starsReply.Select(a => a.Key));
                                                }
                                            }
                                            else
                                            {
                                                if (starsReply?.Count > 0)
                                                {
                                                    // 数据库数据格式化
                                                    var list = fabulousReply.Extend.TrimEnd(',').TrimStart(',').Split(',').ToList();

                                                    // 处理redis获取到的数据
                                                    var redisStars = starsReply.Select(a => a.Key).ToList();

                                                    // 合并结果集并去重
                                                    fabulousReply.Extend = string.Join(',', list.Union(redisStars));
                                                }
                                                else
                                                {
                                                    fabulousReply.Extend = fabulousReply.Extend.TrimEnd(',').TrimStart(',');
                                                }
                                            }


                                            foreach (var attr in itemReply.CommentAttributes)
                                            {
                                                if (attr.Type == (int)CommentAttributeEnum.Fabulous)
                                                {
                                                    attr.Extend = fabulousReply.Extend;
                                                }
                                            }

                                        }
                                    }

                                }
                            }
                        }
                    }

                    return new MethodResult<List<CommentList>> { IsFinished = true, Date = query };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<List<CommentList>> { IsFinished = false, Discription = e.Message };
            }
        }
    }
}
